package org.tissou.server.Utils;

import org.tissou.client.Services.*;
import org.tissou.client.DonneesAAfficher.*;

import java.util.logging.Logger;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

import org.tissou.server.Base.Categorie;
import org.tissou.server.Base.Proprietaire;
import org.tissou.server.Base.Monnaie;

/**
 * Created by Claire
 * User: Claire
 * Date: 28/06/2009
 * Time: tot ce matin la
 * Ceci est l'utilitaire qui va servir a aller chercher des lignes de comptes dans le serveur.
 */
public class RecuperateurDonneesServeur {
  private static final Logger LOG = Logger.getLogger(RecuperateurDonneesServeur.class.getName());
  private static final DateFormat SQL_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd");

  public Donnees_Base RecupererDonnees(ParametresQuery parametres){
    TypeDonnee typeDonnee = parametres.getType();
    String requete = GenererRequete(typeDonnee,parametres);
    ResultSet resultSet = RecupererResultat(requete);
    ContructeurDonneesBases constructeur = new ContructeurDonneesBases();
    return constructeur.ConstruireDonneesBases(resultSet);
  }

  private ResultSet RecupererResultat(String requete) {
    InterfaceMySQL interfacePourLesRequetes = new InterfaceMySQL();
    try {
      LOG.info("Serveur : J'ai reussi a recuperer les donnees.");
      return interfacePourLesRequetes.RecupererDonnees(requete);
    }
    catch (SQLException e) {
      throw new MonException("Je n'ai pas pu recuperer de lignes de comptes", e);
    }
  }

  private String GenererRequete(TypeDonnee typeDonnee, ParametresQuery parametres) {
    StringBuilder requete = new StringBuilder();
    if (typeDonnee == TypeDonnee.LIGNECOMPTEREEL ||typeDonnee == TypeDonnee.LIGNECOMPTEVIRTUEL) {
      int nocompte;
      if (typeDonnee == TypeDonnee.LIGNECOMPTEREEL) {
        nocompte = parametres.getComptes().get(0).getNoCompte();
      } else {
        ProprietaireInfos pprincipale = parametres.getProprietaires().get(0);
        Proprietaire p = Proprietaire.ChargerProprietaire(pprincipale);
        nocompte = p.RenvoyerCompteVirtuel(Monnaie.ChargerMonnaie(parametres.getMonnaies().get(0))).getNoCompte();
      }

      Date date = parametres.getDates().get(0);
      int nombreligne = parametres.getNombredeligne();
      int offset = parametres.getOffset();
      requete.append(String.format("SELECT * FROM transactions WHERE NoCompte = %d", nocompte));
      if (parametres.getNombreProprietaire() > 1) {
        requete.append(String.format(" AND Tiers = '%s'", parametres.getProprietaires().get(1).getNom()));
      }
      if (parametres.getNombreCategories() == 1) {
        // TODO(Clairette): Faire un truc pour pouvoir mettre plus que une categorie ici.
        String toutesLesCategories = parametres.getCategories().get(0).getDescendanceSousFormeDeString();
        requete.append(String.format(" AND Categorie IN (%s)", toutesLesCategories));
      }
       requete.append(String.format(" AND Date <= '%s' ORDER BY Date DESC, NoTransaction DESC",
            SQL_DATE_FORMAT.format(date)));
      requete.append(String.format(" LIMIT %d OFFSET %d", nombreligne, offset));
    }

    else if (typeDonnee == TypeDonnee.DETTES) {
      ProprietaireInfos pprincipale = parametres.getProprietaires().get(0);
      MonnaieInfos monnaie = parametres.getMonnaies().get(0);
      CategorieInfos categorie = parametres.getCategories().get(0);
      Proprietaire p = Proprietaire.ChargerProprietaire(pprincipale);
      Monnaie m = Monnaie.ChargerMonnaie(monnaie);
      Compte c = p.RenvoyerCompteVirtuel(m);
      String ToutesLesCategories = categorie.getDescendanceSousFormeDeString();

      requete.append(String.format("SELECT Tiers,SUM(Somme) FROM transactions WHERE NoCompte = %d AND Categorie IN (%s) " +
          "GROUP BY Tiers",c.getNoCompte(), ToutesLesCategories));
    }
    
    else if (typeDonnee == TypeDonnee.BILANGENERAL || typeDonnee == typeDonnee.BILANGENERALTOTAL) {
	    ProprietaireInfos proprietaire = parametres.getProprietaires().get(0);
	    Date dateInitiale = parametres.getDates().get(0);
	    Date dateFinale = parametres.getDates().get(1);
	    MonnaieInfos monnaie = parametres.getMonnaies().get(0);
	    CategorieInfos categorie = parametres.getCategories().get(0);
	    Proprietaire p = Proprietaire.ChargerProprietaire(proprietaire);
	    Monnaie m = Monnaie.ChargerMonnaie(monnaie);
	    String TousLesComptes = p.ObtenirlisteComptesPourUneMonnaieDonneeSousFormeDeString(m);
	    String ToutesLesCategories = categorie.getDescendanceSousFormeDeString();
	    
	    if (typeDonnee == TypeDonnee.BILANGENERAL){
	    	requete.append(String.format("SELECT Categorie,SUM(Somme) FROM transactions WHERE NoCompte IN (%s) AND Categorie IN (%s) " +
	        "AND Date >= '%s' AND Date <= '%s' GROUP BY Categorie ORDER BY SUM(Somme)",TousLesComptes, ToutesLesCategories, SQL_DATE_FORMAT.format(dateInitiale), SQL_DATE_FORMAT.format(dateFinale)));
	    }
	    else {
	    	requete.append(String.format("SELECT SUM(Somme) FROM transactions WHERE NoCompte IN (%s) AND Categorie IN (%s) " +
	    	        "AND Date >= '%s' AND Date <= '%s'",TousLesComptes, ToutesLesCategories, SQL_DATE_FORMAT.format(dateInitiale), SQL_DATE_FORMAT.format(dateFinale)));
	    }	    
      }
    else {
      throw new MonException("Serveur: Le type d'operation n'a pas ete reconnu");
    }
    return requete.toString();
  }
}



